package com.dayuanit.atm.service.impl;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Random;

import com.dayuanit.atm.dao.DetailDao;
import com.dayuanit.atm.dao.UserDao;
import com.dayuanit.atm.dao.impl.DetailDaoImpl;
import com.dayuanit.atm.dao.impl.UserDaoImpl;
import com.dayuanit.atm.domain.Detail;
import com.dayuanit.atm.domain.User;
import com.dayuanit.atm.service.AtmService;
import com.dayuanit.atm.util.DataBaseUtils;

public class AtmServiceImpl implements AtmService {
	
	private UserDao userDao = new UserDaoImpl();
	private DetailDao detailDao = new DetailDaoImpl();
	
	public void openAccount() {
		String cardNum = createBankNum();
		int balance = 0;
		
		Connection conn = DataBaseUtils.getConn();
		
		//判断生成的卡号是否重复
		User exitUser = userDao.getUserByCardNum(cardNum, conn);
		if (null != exitUser) {
			System.out.println("卡号" + cardNum + "已经存在");
			return;
		}
		
		User user = new User();
		user.setBalance(balance);
		user.setCardNum(cardNum);
		int rows = userDao.addUesr(user, conn);
		if (1 != rows) {
			System.out.println("卡号" + cardNum + "开户失败");
		}
		
		DataBaseUtils.close(conn);
		
	}
	
	public void deposit(int amount, String cardNum) {
		//校验金额
		if (amount <= 0) {
			System.out.println("存款金额必须大于零");
			return;
		}
		
		Connection conn = DataBaseUtils.getConn();
		
		try {
			conn.setAutoCommit(false);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		// 卡号是否存在
//		User exitUser = userDao.getUserByCardNum(cardNum, conn);
		User exitUser = userDao.getUserByCardNumForUpdate(cardNum, conn);
		if (null == exitUser) {
			System.out.println("卡号" + cardNum + "不存在");
			return;
		}
		
//		int rows = userDao.updateBalance(amount, cardNum, exitUser.getVersion(), conn);
		int rows = userDao.updateBalance(amount, cardNum, conn);
		if (1 != rows) {
			System.out.println("卡号" + cardNum + "存钱失败");
			return;
		}
		
		//增加流水
		Detail detail = new Detail();
		detail.setAmount(amount);
		detail.setCardNum(cardNum);
		detail.setOptType(1);
		detail.setTips("存款");
		
		rows = detailDao.addDetail(detail);
		if (1 != rows) {
			System.out.println("卡号" + cardNum + "增加流水失败");
			try {
				conn.rollback();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		try {
			System.out.println(Thread.currentThread().getName() + "睡10秒");
			Thread.sleep(10000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		
		
		
		try {
//			conn.commit();
			conn.rollback();
			System.out.println(Thread.currentThread().getName() + "睡醒啦");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		DataBaseUtils.close(conn);
	}
	
	public void draw(int amount, String cardNum) {
		//校验金额
		if (amount <= 0) {
			System.out.println("取款金额必须大于零");
			return;
		}
		
		try {
			System.out.println(Thread.currentThread().getName() + "要睡5秒");
			Thread.sleep(5000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		
		Connection conn = DataBaseUtils.getConn();
		
		try {
			conn.setAutoCommit(false);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		// 卡号是否存在
//		User exitUser = userDao.getUserByCardNum(cardNum, conn);
		User exitUser = userDao.getUserByCardNumForUpdate(cardNum, conn);
		if (null == exitUser) {
			System.out.println("卡号" + cardNum + "不存在");
			try {
				conn.rollback();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return;
		}
		
		//检查余额是否足够
		if (amount > exitUser.getBalance()) {
			System.out.println("余额不足");
			try {
				conn.rollback();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return;
		}
		
//		int rows = userDao.updateBalance(-amount, cardNum, exitUser.getVersion(), conn);
		int rows = userDao.updateBalance(-amount, cardNum, conn);
		if (1 != rows) {
			System.out.println("卡号" + cardNum + "取钱失败");
			try {
				conn.rollback();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return;
		}
		
		System.out.println("卡号" + cardNum + "取钱成功");
		
		//增加流水
		Detail detail = new Detail();
		detail.setAmount(-amount);
		detail.setCardNum(cardNum);
		detail.setOptType(2);
		detail.setTips("取款");
		
		rows = detailDao.addDetail(detail);
		if (1 != rows) {
			System.out.println("卡号" + cardNum + "增加流水失败");
			try {
				conn.rollback();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		try {
			conn.commit();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		System.out.println(Thread.currentThread().getName() + "取钱成功");
		
		DataBaseUtils.close(conn);
		
	}
	
	private String createBankNum() {
		Random random = new Random();
		String cardNum = "";
		for (int i=0; i<4;i++) {
			int num = random.nextInt(10);
			cardNum += String.valueOf(num);
		}
		
		return cardNum;
	}
	
	public void transfer(int amount, String outCardNum, String inCardNum) {
		//校验金额
		if (amount <= 0) {
			System.out.println("转账金额必须大于零");
			return;
		}
		
		Connection conn = DataBaseUtils.getConn();
		
		try {
			conn.setAutoCommit(false);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		// 卡号是否存在
//		User outUser = userDao.getUserByCardNum(outCardNum, conn);
		User outUser = userDao.getUserByCardNumForUpdate(outCardNum, conn);
		if (null == outUser) {
			System.out.println("卡号" + outCardNum + "不存在");
			return;
		}
		
		User inUser = userDao.getUserByCardNum(inCardNum, conn);
		if (null == inUser) {
			System.out.println("卡号" + inCardNum + "不存在");
			return;
		}
		
		//检查余额是否足够
		if (amount > outUser.getBalance()) {
			System.out.println("余额不足");
			return;
		}
		
		//============= begin ================
				
//		int rows = userDao.updateBalance(-amount, outCardNum, outUser.getVersion(), conn);
		int rows = userDao.updateBalance(-amount, outCardNum, conn);
		if (1 != rows) {
			System.out.println("卡号" + outCardNum + "转账失败");
			return;
		}
		
//		rows = userDao.updateBalance(amount, inCardNum, inUser.getVersion(), conn);
		rows = userDao.updateBalance(amount, inCardNum, conn);
		if (1 != rows) {
			System.out.println("卡号" + outCardNum + "转账失败");
			return;
		}
		
		//增加流水
		Detail detail = new Detail();
		detail.setAmount(-amount);
		detail.setCardNum(outCardNum);
		detail.setOptType(3);
		detail.setTips("转账支出");
		
		rows = detailDao.addDetail(detail);
		if (1 != rows) {
			System.out.println("卡号" + outCardNum + "增加流水失败");
		}
		
		detail = new Detail();
		detail.setAmount(amount);
		detail.setCardNum(inCardNum);
		detail.setOptType(4);
		detail.setTips("转账收入");
		
		rows = detailDao.addDetail(detail);
		if (1 != rows) {
			System.out.println("卡号" + inCardNum + "增加流水失败");
		}
		
		try {
			conn.commit();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		//=========== end ===========
		
		DataBaseUtils.close(conn);
	}
	
	public void queryDetail(String cardNum) {
		Connection conn = DataBaseUtils.getConn();
		
		// 卡号是否存在
		User exitUser = userDao.getUserByCardNum(cardNum, conn);
		if (null == exitUser) {
			System.out.println("卡号" + cardNum + "不存在");
			return;
		}
				
		List<Detail> detailList = detailDao.listDetail(cardNum);
		for (Detail detail : detailList) {
			System.out.println(detail);
		}
		
		DataBaseUtils.close(conn);
	}
	
	public static void main(String[] args) {
		AtmService as = new AtmServiceImpl();
//		as.openAccount();
		
//		as.deposit(100, "1111");
//		as.draw(100, "1111");
		as.transfer(300, "1111", "6085");
//		
//		as.queryDetail("1111");
		
	}
}
